home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 / Documentation / Add-On Docs / Brian's Extensions next >
Encoding:
Text File  |  1999-02-08  |  13.8 KB  |  212 lines  |  [TEXT/ttxt]

  1. Brian's Extensions Read Me and Documentation
  2.  
  3. Brian Roddy (roddy@morpheus.xo.com)
  4. 7/16/97
  5.  
  6. In the SpriteWorld files->Utils->Brian's Extensions folder are some free extensions to SpriteWorld that I've been working on in my free time.  They allow sprites which are translucent, scaled or rotated.   There are also files for doing several different kinds of lighting effects.  Each file has fairly extensive comments and documentation.  In general, each file has general documentation at the top and function specific documentation with the functions.   They have been tested to work with 68K and PowerPC Macintoshes, and have been optimized in some cases with PowerPC assembly code.  They work in 8-Bit or 16-Bit color (i.e. 256 colors or Thousands of Colors).
  7.  
  8. To use these, you simply include the files in your project file.   
  9.  
  10. Also note that translucency, scaling and rotation cannot be combined.  That is, you can't have a scaled translucent sprite.  Although this wouldn't be to hard for the avid programmer.  The blitters are fairly well commented.
  11.  
  12. In addition, none of these extensions were designed to work in a scrolling world. You can try to get them to work in a scrolling game, but there are no guarantees that they will work. Generally, any functions that don't work right when clipping is used won't work properly in a scrolling world. (Such as scaling and rotating.) Translucency and other lighting effects might work in a scrolling game, but haven't been tested.
  13.  
  14. The Extended Sprite Test shows how all of this functionality except the tinting works.  The Lighting Demo shows how tinting works.  Lit Breakout is a more detailed example of the LightingSquares functionality.  All demos and code has been built and tested with Think C 6.0, CodeWarrior 10, and CodeWarrior Pro 1. The demos are not included in the main SpriteWorld package, but are included in the "SpriteWorld 2.1 Extra Demos" package.
  15.  
  16. Below I've copied sections from the top of each source file so you can see the basic documentation all in this one file:
  17.  
  18. -----------------------------------------------------------------------------
  19.  
  20. BlitPixieScaled.c
  21.  
  22. These routines are 8-bit and 16-bit blitters that dynamically shrink or 
  23. stretch the sprite. 
  24.  
  25. Use SWSetSpriteScaledSize to set the scaling size.  When the sprite is drawn, it
  26. will be stretched or shrunk to the new width and height you specify.  
  27. SWSetSpriteScaledSize takes a sprite pointer and a width and a height.  e.g.:
  28.  
  29. SWSetSpriteScaledSize(mySpritePtr, 20, 50);  // Scale it
  30.  
  31. Use a width or height <= 0 to turn off scaling.  Note that just resetting 
  32. the sprite's draw procedure will not turn off scaling properly.  Make sure to 
  33. call SWSetSpriteScaledSize with a negative width or height.  e.g.:
  34.  
  35. SWSetSpriteScaledSize(mySpritePtr, -1, -1);  // Reset it back to normal
  36.  
  37. The maximum scaled width is 800. Values larger than this are permissible as long as the Sprite is clipped so that the visible portion of the Sprite after being clipped is no larger than 800. For instance, if your SpriteWorld's window is 800 pixels wide and your Sprites are clipped to that window, then your may scale your Sprites larger than 800 pixels. Otherwise, you will get an assertion error if you try to scale them larger. You can get around this limitation if necessary; simply change the definition of kMaxScaledWidth at the beginning of  BlitPixieScaled.c to any value, and your Sprites can then be scaled to that maximum size. There is no maximum scaled height; your height can be any size.
  38.  
  39. Also note that scaling is done while drawing to the screen.  As a result, the
  40. pixels in the frames don't match what shows up on the screen.  This means that 
  41. functions which rely on the sprite's mask, such as SWPixelCollision, won't work as 
  42. expected.  Thus using the pixel or mask collision routines with scaled sprites 
  43. won't work accurately.
  44.  
  45. SWSetSpriteScaledSize sets the scaling DrawProc for you automatically, so you don't 
  46. need to call SWSetSpriteDrawProc, unless you want to use a RectDrawProc instead of the 
  47. automatically assigned ScaledMaskDrawProc. It will also change the DrawProc back to one
  48. of the standard BlitPixieMaskDrawProcs when you set the scaled size to -1 to turn off
  49. scaling. Here is a list of the available DrawProcs:
  50.  
  51.     // User DrawProcs:
  52. BlitPixie8BitScaledRectDrawProc
  53. BlitPixie16BitScaledRectDrawProc
  54.  
  55.     // Sprite DrawProcs:
  56. BP8BitScaledSpriteRectDrawProc
  57. BP8BitScaledSpriteMaskDrawProc
  58. BP16BitScaledSpriteRectDrawProc
  59. BP16BitScaledSpriteMaskDrawProc
  60.  
  61. The User DrawProcs are available for you to use directly if you want to do some direct
  62. scaling, such as scaling the contents of the work area as you copy it to the screen.
  63. The Sprite DrawProcs are what you should use when assigning a Sprite a scaling
  64. DrawProc. Do not get these two types of DrawProcs mixed up.
  65.  
  66.  
  67. -----------------------------------------------------------------------------
  68.  
  69. BlitPixieRotated.c
  70.  
  71. These are blitters for rendering rotated versions of a sprite.  The API is simple. Use SWSetSpriteRotation to set the sprite's rotation.  The amount of rotation must be  between 0 to the constant kNumberOfRotationSteps.  Calling SWSetSpriteRotation with 0 as the rotation will reset the sprite to use the standard blitting routines.
  72.  
  73. Example Use:
  74.  
  75. SWSetSpriteRotation(mySpritePtr, 3);  // Rotate it
  76.  
  77. SWSetSpriteRotation(mySpritePtr, 0);  // Reset it back to normal
  78.  
  79.  
  80. Note that all rotation is clipped to frameRect of the sprite.  In other words, the sprite is rotated within it's bounding rectangle.  Thus if you have a long skinny sprite, part of it will be lost while rotating it.  To fix this problem is to make sure that you store the sprite in the resource with enough white space around it that it can rotate fully and have nothing lost.
  81.     
  82. Also note that rotation is done while drawing to the screen.  As a result, it can be fairly slow and the pixels in the frames don't match what shows up on the screen.  This means that functions which rely on the sprite's mask, such as SWPixelCollision, won't work as expected.  Thus using the pixel or mask collisions routines with rotated sprites won't work accurately.
  83.     
  84. Because blitting rotated sprites is slow and there are collision issues, there is a function called CreateRotatedFrameFromFrame that can be called to create a new frame object which contains a rotated version of a frame. In this way the frame is precomputed and blits quickly.  Example Use:
  85.     
  86. for (currentRotation = 1; currentRotation < 8; currentRotation++) 
  87.             CreateRotatedFrameFromFrame(gSpriteWorld, 
  88.                                                                                                                             myFrames[0], 
  89.                                                                                                                             &myFrames[currentRotation], 
  90.                                                                                                                             currentRotation);
  91.     
  92. Imagine an asteroids like game with a single ship image.  This would fill up a frame array with rotated versions of the ship stored in frame zero. 
  93.     
  94.  
  95. One additional technical note.  We need the sin and cos function to do this rotation.  For speed we precompute the values of sin and cos corresponding to each amount of rotation. Since we often want to use 8, 16, 32, or 64 degrees of rotations, arrays of these are predefined in our code.  
  96.  
  97. If we wish to use a different number for kNumberOfRotationSteps, then we need to  uncomment the #define DYNAMICALLY_GENERATE_TABLE in the header file for this code. When DYNAMICALLY_GENERATE_TABLE is defined, we have to call InitializeRotationTables()  to fill up the tables with values.  This requires including MathLib.  If this sounds confusing, just leave kNumberOfRotationSteps with the default value of 32 (or use one of 8, 16, 32, or 64).
  98.  
  99. ----------------------------------------------------------------------------- 
  100.  
  101. SWTranslucentBlitters.c
  102.  
  103. Routines for blitting translucent sprites in 8 bit or in 16 bit mode.  Both versions
  104. require a lookup table to work properly.  These lookup tables need to be initialized
  105. before being used.  To initialize the 16 bit version, call 
  106.  
  107. err = SWCreate16BitTranslucencyTable();
  108.  
  109. This creates a table which supports 30 levels of translucency and is small.  The 8-bit 
  110. table is much bigger.  It requires 256 * 256 bytes (or 64K) of memory for each level
  111. of translucency.  It also takes a relatively long time to compute.  For this reason
  112. we have a number of functions to allow creating these tables in advance and saving them
  113. in the resource fork so they can be loaded quickly.  By default you can call:
  114.  
  115. err = SWLoadOrCreate8BitTranslucencyTable(numLevelsOfTranslucency);
  116.  
  117. This single purpose function will try and load the table from a resource.  If it
  118. does not exist, it will create the table and save it to the resource fork before continuing.
  119. This means that the first time you run the program, it will be slow and will compute
  120. this and save it.  Next time you run the program it can just load it and thus will
  121. start up quickly.  Note that you can go into ResEdit and copy a TTAB resource that
  122. has been computed and paste it into your project's resource file.  This way, it will 
  123. automatically be copied into your application's resource fork at link timeand therefore 
  124. will never have to be computed.  (To reiterate, you run your program first. This 
  125. generates the computed table and stores it in the TTAB resource.  You copy this resource 
  126. into your project's resource file.  From then on this TTAB will get copied to your 
  127. application so you won't have to wait for it to be computed each time you recompile 
  128. and run.)
  129.  
  130. More detailed functions for manipulating these tables exist.  See the source code
  131. for more details in the comments.
  132.  
  133.  
  134. Once you've called initialized the table or tables, you can set a Sprite's translucency
  135. level with:
  136.  
  137. SWSetSpriteTranslucencyLevel(mySpritePtr, 6)
  138.  
  139. where mySpritePtr is a SpritePtr and 6 is a byte specifying the translucency level.
  140. This level is a number from 1 to the number of Levels, where 1 is barely
  141. visible and a higher number is more opaque.  If a level of any other value (e.g. 0
  142. or >= number of levels)    is specified, the Sprite is considered fully opaque and is 
  143. thus blitted normally. SWSetSpriteTranslucencyLevel automatically sets the Sprite's DrawProc to one of the translucent blitters.
  144.  
  145. You can find a sprite's level of translucency with 
  146.  
  147. SWGetSpriteTranslucencyLevel(mySpritePtr)
  148.  
  149. which will return the level as a byte, or 0 if the sprite is opaque.
  150.  
  151. IMPORTANT: The translucent blitters and idle Sprites do not mix! This means that each
  152. translucent Sprite should have a MoveProc or FrameProc that is called every frame that
  153. sets the Sprite's needsToBeDrawn flag to true.
  154.  
  155. -----------------------------------------------------------------------------
  156.  
  157. SWLightingSquares.c
  158.  
  159.  ** N.B. These functions are still relatively experimental.  They work fine, but the public API needs work to achieve better effects and uses.
  160.  
  161. These routines are for an alternative style of getting lighting effects.  It's main function is a Screen Blitting procedures that takes the offscreen work area and colors it as it copies it on screen.  Thus the parts copied on screen can  be made darker or lighter or a little reddish, etc.  
  162.  
  163. To support a feeling of lights, we divide the screen into a map of tiny squares  and associate a color and a level with each square.  As we blit onto the screen, we use this map to color the image.  The result is that the screen image looks nicely colorized.  Imagine each square having a colored gel placed over top of  it.
  164.  
  165. The smaller the squares in our map, the finer the grain of lighting but the greater the overhead.  More space and speed are required.  We also provide routines for setting  and managing this lighting map, including setting light levels and combining  lights (so blue lights and yellow lights will become greenish lights as they overlap).
  166.  
  167. These functions make use of the translucency table functions found in  "SWTranslucentBlitters.c" and therefore that file needs to be present for this to work.
  168.  
  169. Use SWInitializeLightingSquares(spriteWorldPtr, 8); to initialize the use of squares. 8 in this case is the size of the squares in pixels.  
  170.  
  171. Use:     
  172.  
  173. SWSetLightingSquare(spriteWorldPtr, col, row, color, opacity,                          
  174.                     relativeP, makeDirtyP); 
  175.  
  176. to set a cell's value.  Opacity is the translucency levels (as in the translucent blitters). relativeP is a boolean specifying whether to set the color and level directly or to blend it together with what is already in the cell.   makeDirtyP forces sprite world to redraw that cell on the screen during the next draw loop.
  177.  
  178. Use:     
  179.  
  180. SWLightUpArea (spriteWorldPtr, col, row,                  
  181.                   color,  level                         
  182.                bigLightP); 
  183.  
  184. to light up an area around a cell.  This is good for spotlights.  bigLightP makes the light really big.  Note that this just calls     SWSetLightingSquare repeatedly.        
  185.  
  186. SWDarkenLightingSquares (spriteWorldPtr); will blend black into every square in the grid to darken everything.  This is a good example of how to achieve a lighting effect with these squares.
  187.  
  188. Use 
  189.  
  190. SWExitLightingSquares (); 
  191.  
  192. to free up the tables when quitting.  
  193.  
  194. The Lit Breakout Demo is an example of how to use these functions in an app.
  195.  
  196. -----------------------------------------------------------------------------
  197.  
  198. SWTinting.c
  199.  
  200. - Functions for tinting SpriteWorld graphics a particular color.   
  201. - Functions for using tinting to implement basic lighting techniques on           
  202.         sprites and tiles.
  203.  
  204. This style of lighting works well with tiles with a single kind of light.  This is because we precompute all of the sprites and tiles at the different light levels.  This makes it fast, but not very flexible.  See "SWLightingSquares.c" for another approach to lighting which is slightly slower, but is dynamic and handles an arbitrary number of colored lights.
  205.  
  206. Functionality documented above each function.  See the Lighting Demo for a representative example of how to use everything.
  207.  
  208. -----------------------------------------------------------------------------
  209.  
  210.  
  211. This is all provided as is with no promises or guarantees.  Don't count on me for support, service, or coherency.  And don't blame anyone else for my mistakes.  Thanks are always appreciated.  Drop me a line if this stuff is useful.
  212.